1
namespace Org
.Lwes
.Tests
4 using System
.Collections
.Generic
;
7 using System
.Threading
;
9 using Microsoft
.VisualStudio
.TestTools
.UnitTesting
;
12 /// Summary description for StatusTests
15 public class StatusTests
31 #endregion Enumerations
35 public TestContext TestContext
45 public void TestParallelStateTransitions()
47 // The intention here is to cause maximum contention on the Status<> class's methods
48 // and thereby provide sufficient confidence that the class provides non-blocking,
49 // thread-safe state transitions.
52 NumberOfThreadsPerState
= 10,
53 WaitPulseMilliseconds
= 200,
54 MainThreadWaitTimeBeforeShutdown
= TimeSpan
.FromSeconds(10)
57 Status
<TestStates
> state
= new Status
<TestStates
>(default(TestStates
));
58 int onThreadsStarted
= 0;
59 int offThreadsStarted
= 0;
60 int undecidedThreadsStarted
= 0;
62 int transitionsOn
= 0;
63 int transitionsOff
= 0;
64 int transitionsUndecided
= 0;
65 int transitionsOnStateDone
= 0;
66 int transitionsOffStateDone
= 0;
67 int transitionsDone
= 0;
69 for (int i
= 0; i
< control
.NumberOfThreadsPerState
; i
++)
71 // These background jobs transition the state from TestStates.Undecided
72 // to TestStates.On - when successful it increments transitionsOn.
73 ThreadPool
.QueueUserWorkItem(new WaitCallback((unused_state
) =>
75 state
.SpinWaitForState(TestStates
.Undecided
, () => Thread
.Sleep(control
.WaitPulseMilliseconds
));
76 Interlocked
.Increment(ref onThreadsStarted
);
77 while (state
.IsLessThan(TestStates
.ShutdownSignaled
))
79 state
.TryTransition(TestStates
.On
, TestStates
.Undecided
, () =>
81 Interlocked
.Increment(ref transitionsOn
);
84 state
.TryTransition(TestStates
.OnStateDone
, TestStates
.ShutdownSignaled
, () =>
86 Interlocked
.Increment(ref transitionsOnStateDone
);
89 // These background jobs transition the state from TestStates.On
90 // to TestStates.Off - when successful it increments transitionsOff.
91 ThreadPool
.QueueUserWorkItem(new WaitCallback((unused_state
) =>
93 state
.SpinWaitForState(TestStates
.On
, () => Thread
.Sleep(control
.WaitPulseMilliseconds
));
94 Interlocked
.Increment(ref offThreadsStarted
);
96 while(state
.IsLessThan(TestStates
.OnStateDone
))
98 state
.TryTransition(TestStates
.Off
, TestStates
.On
, () =>
100 Interlocked
.Increment(ref transitionsOff
);
103 state
.TryTransition(TestStates
.OffStateDone
, TestStates
.OnStateDone
, () =>
105 Interlocked
.Increment(ref transitionsOffStateDone
);
108 // These background jobs transition the state from TestStates.Off
109 // to TestStates.Undecided - when successful it increments transitionsUndecided.
110 ThreadPool
.QueueUserWorkItem(new WaitCallback((unused_state
) =>
112 state
.SpinWaitForState(TestStates
.Off
, () => Thread
.Sleep(control
.WaitPulseMilliseconds
));
113 Interlocked
.Increment(ref undecidedThreadsStarted
);
115 while (state
.IsLessThan(TestStates
.OffStateDone
))
117 state
.TryTransition(TestStates
.Undecided
, TestStates
.Off
, () =>
119 Interlocked
.Increment(ref transitionsUndecided
);
123 state
.TryTransition(TestStates
.Done
, TestStates
.OffStateDone
, () =>
125 Interlocked
.Increment(ref transitionsDone
);
130 // Signal the first group of threads that they should start.
131 state
.SetState(TestStates
.Undecided
);
133 // Wait the prescribed amount of time...
134 Thread
.Sleep(control
.MainThreadWaitTimeBeforeShutdown
);
135 // Signal the shutdown...
136 state
.SetState(TestStates
.ShutdownSignaled
);
137 // Wait for background threads to shutdown...
138 state
.SpinWaitForState(TestStates
.Done
, () => Thread
.Sleep(control
.WaitPulseMilliseconds
));
140 Assert
.IsTrue(Thread
.VolatileRead(ref transitionsOn
) >= Thread
.VolatileRead(ref transitionsOff
));
141 Assert
.IsTrue(Thread
.VolatileRead(ref transitionsOff
) >= Thread
.VolatileRead(ref transitionsUndecided
));
142 Assert
.AreEqual(1, Thread
.VolatileRead(ref transitionsOnStateDone
));
143 Assert
.AreEqual(1, Thread
.VolatileRead(ref transitionsOffStateDone
));
144 Assert
.AreEqual(1, Thread
.VolatileRead(ref transitionsDone
));
146 Console
.WriteLine(String
.Concat("Threads transitioninig to On: ", onThreadsStarted
, ", transitions = ", transitionsOn
));
147 Console
.WriteLine(String
.Concat("Threads transitioninig to Off: ", offThreadsStarted
, ", transitions = ", transitionsOff
));
148 Console
.WriteLine(String
.Concat("Threads transitioninig to Undecided: ", undecidedThreadsStarted
, ", transitions = ", transitionsUndecided
));